﻿using System;
using Microsoft.SharePoint;

namespace SharePoint.Orm.Helpers {
	public static class SPSecurityHelper {
		public static void RunInElevatedSite(SPWeb site, SPListItem item, Action<SPWeb, SPListItem> action) {
			using (SPSite elevSiteCollection = CreateElevatedSite(site.Site))
			using (SPWeb elevSite = elevSiteCollection.OpenWeb(site.ID)) {
				SPListItem elemItem = elevSite.Lists[item.ParentList.ID].GetItemById(item.ID);
				action(elevSite, elemItem);
			}
		}

		public static void RunInElevatedSite(SPWeb site, Action<SPWeb> action) {
			using (SPSite elevSiteCollection = CreateElevatedSite(site.Site))
			using (SPWeb elevSite = elevSiteCollection.OpenWeb(site.ID)) {
				action(elevSite);
			}
		}

		public static SPSite CreateElevatedSite(SPSite siteCollection) {
			SPUserToken sysToken = GetSystemToken(siteCollection);
			return new SPSite(siteCollection.ID, sysToken);
		}

		private static SPUserToken GetSystemToken(SPSite siteCollection) {
			siteCollection.CatchAccessDeniedException = false;
			try {
				return siteCollection.SystemAccount.UserToken;
			} catch (UnauthorizedAccessException) {
				SPUserToken sysToken = null;
				SPSecurity.RunWithElevatedPrivileges(() => {
					using (SPSite elevSiteCollection = new SPSite(siteCollection.ID)) {
						sysToken = elevSiteCollection.SystemAccount.UserToken;
					}
				});
				if (sysToken == null) {
					throw;
				}
				return sysToken;
			} finally {
				siteCollection.CatchAccessDeniedException = true;
			}
		}
	}
}
